/*
* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd. 
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "ai_interpreter.h"
#include "utils/log/infer_log.h"
#include "infer_framework_factory.h"

AIInterpreter::AIInterpreter(const AlgorithmInfo &algoConfig)
    : isLoad_(false), algoConfig_(algoConfig), inferWrapper_(nullptr)
{
    AiRetCode returnCode = Init();
    if (returnCode != AiRetCode::AI_RETCODE_SUCCESS) {
        HILOGE("In AIInterpreter, Init error");
    }
}

AIInterpreter::~AIInterpreter() = default;

AiRetCode AIInterpreter::Init()
{
    InferFramework *inferPtr = InferFrameworkFactory::Create(algoConfig_);
    if (inferPtr == nullptr) {
        HILOGE("get wrapper failed");
        return AiRetCode::AI_RETCODE_FAILURE;
    }
    inferWrapper_.reset(inferPtr);
    return AiRetCode::AI_RETCODE_SUCCESS;
}

AiRetCode AIInterpreter::Term()
{
    inferWrapper_.reset();
    return AiRetCode::AI_RETCODE_SUCCESS;
}

AiRetCode AIInterpreter::Load()
{
    if (isLoad_) {
        HILOGE("Load() has been executed [LOAD_REPEATED]");
        return AiRetCode::AI_RETCODE_FAILURE;
    }

    if (inferWrapper_.get() == nullptr) {
        HILOGE("inferWrapper_.get() [INVALID_POINTER]");
        return AiRetCode::INVALID_POINTER;
    }

    AiRetCode returnCode = inferWrapper_->Load();
    if (returnCode != AiRetCode::AI_RETCODE_SUCCESS) {
        HILOGE("inferWrapper_->Load() [FAIL] returnCode:%d", (int)returnCode);
        return returnCode;
    }

    isLoad_ = true;
    return AiRetCode::AI_RETCODE_SUCCESS;
}

AiRetCode AIInterpreter::SyncInfer( std::vector<IOTensor> &inputs, std::vector<IOTensor> &outputs) const
{
    if (isLoad_ == false) {
        HILOGE("Load has not been executed [LOAD_NOT_EXECUTED]");
        return AiRetCode::AI_RETCODE_FAILURE;
    }

    if (inferWrapper_.get() == nullptr) {
        HILOGE("inferWrapper_.get() == nullptr [INVALID_POINTER]");
        return AiRetCode::INVALID_POINTER;
    }
    AiRetCode returnCode = inferWrapper_->SynInfer(inputs, outputs);
    if (returnCode != AiRetCode::AI_RETCODE_SUCCESS) {
        HILOGE("inferWrapper_->Invoke(inputs, outputs) [FAIL] returnCode:%d", (int)returnCode);
    }

    return returnCode;
}

AiRetCode AIInterpreter::Unload()
{
    if (isLoad_ == false) {
        HILOGE("Load() has not been executed [UNLOAD_REPEATED]");
        return AiRetCode::AI_RETCODE_FAILURE;
    }

    if (inferWrapper_.get() == nullptr) {
        HILOGE("inferWrapper_.get() == nullptr [INVALID_POINTER]");
        return AiRetCode::INVALID_POINTER;
    }

    AiRetCode returnCode = inferWrapper_->Unload();
    if (returnCode != AiRetCode::AI_RETCODE_SUCCESS) {
        HILOGE("inferWrapper_->Unload() [FAIL] returnCode:%d", (int)returnCode);
        return returnCode;
    }

    isLoad_ = false;
    return AiRetCode::AI_RETCODE_SUCCESS;
}
